<?php
class Model extends Zpdo{
	private static $dbconf;
	private $dbconn;
	protected $table;
	private $rowcount = 0;
	private $condition;
	protected $param = array();
	
	function __construct($tablename='') {
		$this->table($tablename);
		if(!self::$dbconf)
			self::$dbconf = include(_CONFIG_ . "/db_conf.php");	
		$this->connect();
	}
	
	protected function connect() {
		if(!$this->dbconn){
	        try {
	            $h_param = array(
	                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
	            );
	            if (self::$dbconf['DB_CHARSET'] != '') {
	                $h_param[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . self::$dbconf['DB_CHARSET'];
	            }
	            if (self::$dbconf['DB_PCONNECT']) {
	                $h_param[PDO::ATTR_PERSISTENT] = true;
	            }
	            $dsn = "mysql:host=" . self::$dbconf['DB_HOST'] . ";port=" . self::$dbconf['DB_PORT'] . ";dbname=" . self::$dbconf['DB_NAME'];
	            $this->dbconn = new PDO($dsn, self::$dbconf['DB_USER'], self::$dbconf['DB_PWD'], $h_param);
	        } catch (PDOException $e) {
	            throw new ErrorException('Unable to connect to db server. Error:' . $e->getMessage(), 31);
	        }
		}
    }
	
    public function table($tablename) {
    	if(is_string($tablename))
    	 $this->table = $tablename;
    	 return $this;
    }
    
	public function set($param) {
    	if(is_array($param))
    		$this->param = $param;
    	return $this;
    }

    public function where($condition) {
    	if(is_string($condition))
			$this->condition = $condition;
		return $this;
    }
    
    public function find($param='',$fetchmode='hash') {
    	if(is_array($param)) $this->set($param);
    	if(is_string($param)&&empty($fetchmode)) $fetchmode = $param;
    	
		$table = isset($this->param['table']) && !empty($this->param['table']) ?$this->param['table'] : $this->table;
		$field = isset($this->param['field']) && !empty($this->param['field']) ? $this->param['field'] : '*';
        $where = isset($this->param['where']) && !empty($this->param['where']) ? 'where ' . $this->param['where'] : '';
        $group = isset($this->param['group']) && !empty($this->param['group']) ? 'group by ' . $this->param['group'] : '';
        $order = isset($this->param['order']) && !empty($this->param['order']) ? 'order by ' . $this->param['order'] : '';
        $limit = isset($this->param['limit']) && !empty($this->param['limit']) ? 'limit ' . $this->param['limit'] : '';
        $pagesize = isset($this->param['pagesize']) && !empty($this->param['pagesize']) ? $this->param['pagesize'] : 0;
        $page = isset($this->param['page']) && !empty($this->param['page']) ? $this->param['page'] : 1;
        $join = isset($this->param['join']) && !empty($this->param['join']) ? $this->param['join'] : '';
        $on = isset($this->param['on']) && !empty($this->param['on']) ? 'on ' . $this->param['on'] : '';
		if (!is_numeric($page) || $page <= 0)
			$page = 1;
        $startpage = ($page - 1) * $pagesize;
		$sqlstr = $pagesize > 0 ? "select $field from $table $join $on $where $group $order limit $startpage,$pagesize" : "select $field from $table $join $on $where $group $order $limit";
		$sth = $this->dbconn->prepare($sqlstr);
        $sth->execute();
        $this->rowcount = (int) $sth->rowCount();
		switch ($fetchmode) {
            case 'num':
                $result = $sth->fetchAll(PDO::FETCH_NUM);
                break;
            case 'hash':
                $result = $sth->fetchAll(PDO::FETCH_ASSOC);
                break;
            case 'one':
                $result = $sth->fetch();
                break;
            case 'all':
            default:
                $result = $sth->fetchAll();
        }
        $this->param = null;
        return $result;
	}

	public function add($param = '') {
		if(is_array($param)) $this->set($param);
		$table = $this->table;
		$a_add_placeholder = $a_add_field = $a_add_value = array();
        foreach ($this->param as $a_add_field[] => $a_add_value[]) {
            array_push($a_add_placeholder, '?');
        }
        $add_part = '`' . implode('`,`', $a_add_field) . '`';
        $placeholder_part = implode(',', $a_add_placeholder);
        $sth = $this->dbconn->prepare("insert into $table ($add_part) values ($placeholder_part)");
        $sth->execute($a_add_value);
        $this->param = null;
        return $this->dbconn->lastInsertId();
	}
	
	public function delete($tablename = '', $condition = '') {
		if(!empty($tablename)) $this->table($tablename);
    	if(!empty($tablename)&&empty($condition)) $condition = $tablename;
    	if(!empty($condition)) $this->where($condition);
		
		$table = $this->table;
		$where = $this->condition;
		$this->dbconn->query("delete from $table where $where") or die($this->dbconn->errorInfo());
	}
	
	public function update($param = '', $condition = '') {
		if(is_array($param)) $this->set($param);
    	if(is_string($param)&&empty($condition)) $condition = $param;
    	if(!empty($condition)) $this->where($condition);
		
		$table = $this->table;
		$where = $this->condition;
		$a_update_field = array();
        $a_update_value = array();

        foreach ($this->param as $colname => $a_update_value[]) {
            array_push($a_update_field, "`$colname`=?");
        }
        $update = implode(',', $a_update_field);
        if (!empty($where)) {
            $sth = $this->dbconn->prepare("update $table set $update where $where");
        } else {
            $sth = $this->dbconn->prepare("update $table set $update");
        }
        $sth->execute($a_update_value);
        $rows_affected = $sth->rowCount();
        $this->param = null;
        return $rows_affected;
	}	
	
	public function count($param='') {
    	$this->find($param);
        return $this->rowcount;
	}
	
	public function get_count() {
        return $this->rowcount;
	}
	
	public function handle($sqlstr = '') {
        $types = explode(' ', $sqlstr);
        $type = strtolower($types[0]);
        switch ($type) {
            case 'select':
                $sth = $this->dbconn->prepare($sqlstr);
                $sth->execute();
                $result = $sth->fetchAll(PDO::FETCH_ASSOC);
                return $result;
                break;

            case 'insert':
                $this->dbconn->query($sqlstr) or die($this->dbconn->errorInfo());
                return $this->dbconn->lastInsertId();
                break;

            case 'update':
                $sth = $this->dbconn->query($sqlstr) or die($this->dbconn->errorInfo());
                return $sth->rowCount();
                break;

            case 'delete':
                $this->dbconn->query($sqlstr) or die($this->dbconn->errorInfo());
                return true;
                break;

            case 'replace':
                $this->dbconn->query($sqlstr) or die($this->dbconn->errorInfo());
                return $this->dbconn->lastInsertId();
                break;

            default:
                $this->dbconn->query($sqlstr) or die($this->dbconn->errorInfo());
        }
    }
	
}
?>